package com.dashan.frontend.client.widgets;

import static com.dashan.Constants.*;
import static com.dashan.Constants.CURRENT_ONLY;
import static com.dashan.Constants.FRIENDNAME;
import static com.dashan.Constants.SESSIONID;
import static com.dashan.Constants.TRUE;
import static com.dashan.Constants.USERNAME;

import java.util.Date;

import com.dashan.frontend.client.DashanCookie;
import com.dashan.frontend.client.model.Position;
import com.dashan.frontend.client.util.DashanRequestBuilder;
import com.dashan.frontend.client.util.DashanXmlReader;
import com.dashan.frontend.client.util.GoogleMap;
import com.dashan.frontend.client.widgets.GeoGridPanel.GeoRecord;
import com.google.gwt.http.client.Request;
import com.google.gwt.http.client.RequestCallback;
import com.google.gwt.http.client.RequestException;
import com.google.gwt.http.client.Response;
import com.google.gwt.maps.client.geom.LatLng;
import com.google.gwt.maps.client.geom.LatLngBounds;
import com.google.gwt.maps.client.overlay.Marker;
import com.google.gwt.maps.client.overlay.MarkerOptions;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.ui.Composite;
import com.gwtext.client.core.EventObject;
import com.gwtext.client.data.FieldDef;
import com.gwtext.client.data.FloatFieldDef;
import com.gwtext.client.data.IntegerFieldDef;
import com.gwtext.client.data.Record;
import com.gwtext.client.data.RecordDef;
import com.gwtext.client.data.SimpleStore;
import com.gwtext.client.data.Store;
import com.gwtext.client.data.StringFieldDef;
import com.gwtext.client.data.XmlReader;
import com.gwtext.client.widgets.Button;
import com.gwtext.client.widgets.Panel;
import com.gwtext.client.widgets.event.ButtonListenerAdapter;
import com.gwtext.client.widgets.form.ComboBox;
import com.gwtext.client.widgets.form.event.ComboBoxListenerAdapter;
import com.gwtext.client.widgets.grid.CellMetadata;
import com.gwtext.client.widgets.grid.ColumnConfig;
import com.gwtext.client.widgets.grid.ColumnModel;
import com.gwtext.client.widgets.grid.GridView;
import com.gwtext.client.widgets.grid.Renderer;

public class PublicSearchPanel extends Composite {

    private static final String GENDER = "gender";
    private static final String LASTONLINE = "lastonline";
    private static final String DISTANCE = "distance";
    private static final String STATUS = "status";
    private static final String NICKNAME = "nickName";
    
    final GeoGridPanel grid;
    final RecordDef recordDef = new RecordDef(new FieldDef[] { 
            new StringFieldDef(USERNAME), 
            new StringFieldDef(NICKNAME),
            new StringFieldDef(GENDER), 
            new StringFieldDef(STATUS), 
            new FloatFieldDef(DISTANCE),
            new IntegerFieldDef(LASTONLINE) });

    private Panel root = new Panel();
    private MainPanel mainPanel;
    private Button inMapSearchButton = new Button("图上搜索");
    
    public PublicSearchPanel(MainPanel mainPanel) {
        this.mainPanel = mainPanel;
        root.setPaddings(10);
        grid = new GeoGridPanel(mainPanel.getGoogleMap(), recordDef);
        initCitiSelection();
        initSearchInMap();
        initGrid();
        initWidget(root);
    }
    
    private void initCitiSelection() {

        // create a Store using local array data
        final Store store = new SimpleStore(new String[] { "city", "lon", "lat", "zoom" },
                getCities());
        store.load();
        final ComboBox cb = new ComboBox();
        cb.setForceSelection(true);
        cb.setMinChars(1);
        cb.setFieldLabel("城市");
        cb.setStore(store);
        cb.setDisplayField("city");
        cb.setMode(ComboBox.LOCAL);
        cb.setTriggerAction(ComboBox.ALL);
        cb.setTypeAhead(true);
        cb.setSelectOnFocus(true);
        cb.setWidth(100);
        cb.setHideTrigger(false);
        root.add(cb);

        cb.addListener(new ComboBoxListenerAdapter() {
            @Override
            public void onSelect(ComboBox comboBox, Record record, int index) {
                LatLng city = LatLng.newInstance(record.getAsDouble("lat"), record
                        .getAsDouble("lon"));
                mainPanel.getGoogleMap().getMap().setCenter(city);
                mainPanel.getGoogleMap().getMap().setZoomLevel(record.getAsInteger("zoom"));
                inMapSearch();
            }
        });
    }
    
    private void initSearchInMap() {
        inMapSearchButton.addListener(new ButtonListenerAdapter() {
            @Override
            public void onClick(Button button, EventObject e) {
                inMapSearch();
            }
        });
        
        root.add(inMapSearchButton);
    }
    
    private void addBuddy(final String userName) {
        final long now = new Date().getTime();
        DashanRequestBuilder builder = new DashanRequestBuilder("/getuser");
        builder.addUserParam();
        
        builder.addParameter(FRIENDNAME, userName);
        try {
            builder.sendRequest(new RequestCallback() {
                
                @Override
                public void onResponseReceived(Request request, Response response) {
                    if (Response.SC_OK == response.getStatusCode()) {
                        
                        Record[] records = DashanXmlReader.fetchFromXml(response.getText(), 
                                new XmlReader("user", new RecordDef(
                                        new FieldDef[] {new StringFieldDef(NICKNAME), 
                                                        new StringFieldDef(STATUS),
                                                        new StringFieldDef(GENDER)})));
                        Record[] positions = DashanXmlReader.fetchFromXml(response.getText(), 
                                new XmlReader("position", new RecordDef(
                                        new FieldDef[] {new StringFieldDef("lng_lat_acc"), 
                                                new StringFieldDef("timestamp_long")})));

                        if (records.length  == 1 && positions.length == 1) {
                            Record p = positions[0];
                            
                            Position pos = new Position(p.getAsString("lng_lat_acc"), 
                                    new Date(Long.parseLong(p.getAsString("timestamp_long"))));
                            Record r = records[0];
                            Record record = recordDef.createRecord(new Object[] { 
                                    userName, 
                                    r.getAsString(NICKNAME),
                                    r.getAsString(GENDER),
                                    r.getAsString(STATUS),
                                    //current position - b.getPosistion;
                                    100.3, 
                                    now - pos.getTimestamp().getTime()});
                            MarkerOptions opt = MarkerOptions.newInstance(GoogleMap.ICON);
                            Marker m = new Marker(LatLng.newInstance(pos.getLatitude(), pos
                                    .getLongitude()), opt);
                            grid.addGeoRecord(new GeoRecord(record, m));
                        } else {
                            Window.alert("Response Error!");
                        }
                    } else {
                        Window.alert(response.getText());
                    }
                }

                @Override
                public void onError(Request request, Throwable exception) {
                    Window.alert("Fail to get resopnse");
                }
            });
        } catch (RequestException e) {
            Window.alert("Fail to get resopnse");
            e.printStackTrace();
        }
    }
    
    public void onShow() {
        grid.showMarker();
    }    
    
    private void initGrid() {
        ColumnConfig userName = new ColumnConfig("用户", NICKNAME, 1, true);

        userName.setWidth(50);
        ColumnConfig lastOnline = new ColumnConfig("上次更新", LASTONLINE, 1, true, new Renderer() {
            @Override
            public String render(Object value, CellMetadata cellMetadata, Record record,
                    int rowIndex, int colNum, Store store) {
                long lastOnline = record.getAsInteger(LASTONLINE);
                String res = " 之前";
                lastOnline /= 1000 * 60;
                if (lastOnline != 0) {
                    res = (lastOnline % 60) + "分" + res;
                    lastOnline /= 60;
                }
                if (lastOnline != 0) {
                    res = (lastOnline % 24) + "小时" + res;
                    lastOnline /= 24;
                }
                if (lastOnline != 0) {
                    res = (lastOnline) + "天" + res;
                }
                return res;
            }
        });
        lastOnline.setWidth(50);

        ColumnConfig distance = new ColumnConfig("距离", USERNAME, 1, true, new Renderer() {
            @Override
            public String render(Object value, CellMetadata cellMetadata, Record record,
                    int rowIndex, int colNum, Store store) {
                return record.getAsString(DISTANCE);
            }
        });
        distance.setWidth(30);
        
        ColumnModel columnModel = 
            new ColumnModel(new ColumnConfig[] {userName, lastOnline, distance});
        grid.setColumnModel(columnModel);

        grid.setHeight(500);
        grid.setWidth(275);
        grid.setMargins(10, 0, 0, 0);
        
        GridView view = new GridView() {
            public String getRowClass(Record record, int index,
                    final com.gwtext.client.widgets.grid.RowParams rowParams, Store store) {
                rowParams.setBody(record.getAsString(STATUS));
                String genderClass = "";
                if (record.getAsString(GENDER) != null) {
                    if (record.getAsString(GENDER).compareTo(FEMALE) == 0) {
                        genderClass = "female_row";
                    } else if (record.getAsString(GENDER).compareTo(MALE) == 0) {
                        genderClass = "male_row";
                    }
                }
                return "x-grid3-row-expanded " + genderClass;
            };
        };

        view.setForceFit(true);
        view.setEnableRowBody(true);
        grid.setView(view);
        
        root.add(grid);
    }
    
    private void inMapSearch() {
        grid.clearData();
        
        LatLngBounds bounds = mainPanel.getGoogleMap().getMap().getBounds();

        DashanRequestBuilder builder = new DashanRequestBuilder("/geosearch");
        DashanCookie cookie = DashanCookie.load();
        if (cookie == null) {
            builder.addParameter(USERNAME, "");
            builder.addParameter(SESSIONID, "0");
        } else {
            builder.addParameter(USERNAME, cookie.getUserName());
            builder.addParameter(SESSIONID, cookie.getSessionId());
        }
        builder.addParameter(CURRENT_ONLY, TRUE);
        builder.addParameter(BOUNDING_BOX, bounds.getNorthEast().getLatitude() + ", "
                + bounds.getSouthWest().getLatitude() + ", "
                + bounds.getNorthEast().getLongitude() + ", "
                + bounds.getSouthWest().getLongitude());
        try {
            builder.sendRequest(new RequestCallback() {

                @Override
                public void onResponseReceived(Request request, Response response) {
                    if (Response.SC_OK == response.getStatusCode()) {
                        Record[] records = DashanXmlReader.fetchFromXml(response.getText(),
                                new XmlReader("position", new RecordDef(
                                        new FieldDef[] { new StringFieldDef("username")})));

                        for (Record r : records) {
                            addBuddy(r.getAsString("username"));
                        }
                    } else {
                        Window.alert(response.getText());
                    }
                }

                @Override
                public void onError(Request request, Throwable exception) {
                    Window.alert("Fail to get resopnse");
                }
            });
        } catch (RequestException e) {
            Window.alert("Fail to get resopnse");
            e.printStackTrace();
        }
    }


    
    private static String[][] getCities() {
        return new String[][] { new String[] { "北京", "116.41667", "39.91667", "11" },
                new String[] { "上海", "121.43333", "31.24", "11" },
                new String[] { "天津", "117.2", "39.13333", "11" },
                new String[] { "香港", "114.1", "22.2", "11" },
                new String[] { "广州", "113.23333", "23.16667", "11" },
                new String[] { "珠海", "113.51667", "22.3", "11" },
                new String[] { "深圳", "114.06667", "22.61667", "11" },
                new String[] { "杭州", "120.2", "30.26667", "11" },
                new String[] { "重庆", "106.45", "29.56667", "11" },
                new String[] { "青岛", "120.33333", "36.06667", "11" },
                new String[] { "厦门", "118.1", "24.46667", "11" },
                new String[] { "福州", "119.3", "26.08333", "11" },
                new String[] { "兰州", "103.73333", "36.03333", "11" },
                new String[] { "贵阳", "106.71667", "26.56667", "11" },
                new String[] { "长沙", "113", "28.21667", "11" },
                new String[] { "南京", "118.78333", "32.05", "11" },
                new String[] { "南昌", "115.9", "28.68333", "11" },
                new String[] { "沈阳", "123.38333", "41.8", "11" },
                new String[] { "太原", "112.53333", "37.86667", "12" },
                new String[] { "成都", "104.06667", "30.66667", "11" },
                new String[] { "拉萨", "91", "29.6", "11" },
                new String[] { "乌鲁木齐", "87.68333", "43.76667", "11" },
                new String[] { "昆明", "102.73333", "25.05", "11" },
                new String[] { "西安", "108.95", "34.26667", "11" },
                new String[] { "西宁", "101.75", "36.56667", "11" },
                new String[] { "银川", "106.26667", "38.46667", "11" },
                new String[] { "兰浩特", "122.08333", "46.06667", "11" },
                new String[] { "哈尔滨", "126.63333", "45.75", "11" },
                new String[] { "长春", "125.35", "43.88333", "11" },
                new String[] { "武汉", "114.31667", "30.51667", "11" },
                new String[] { "郑州", "113.65", "34.76667", "11" },
                new String[] { "石家庄", "114.48333", "38.03333", "11" },
                new String[] { "三亚", "109.5", "18.2", "11" },
                new String[] { "海口", "110.35", "20.01667", "11" },
                new String[] { "澳门", "113.5", "22.2", "11" } };
    }
}
